Apprendre Go en 10 minutes
Go (également connu sous le nom de Golang) est un langage de programmation compilé et statiquement typé conçu chez Google. Il est connu pour sa simplicité, son efficacité et son excellent support pour la concurrence. Ce tutoriel vous aidera à apprendre rapidement la programmation en Go.
1. Écrire votre premier programme Go
Commençons par un programme simple. Créez un fichier nommé hello.go
et entrez le code suivant :
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Sauvegardez le fichier et exécutez la commande suivante dans le terminal :
go run hello.go
Le résultat sera :
Hello, World!
Ce programme simple démontre la structure de base de Go :
package main
déclare le nom du packageimport "fmt"
importe le package de format pour les opérations d’entrée/sortiefunc main()
est le point d’entrée du programmefmt.Println()
affiche du texte dans la console
2. Syntaxe de base
Go a une syntaxe claire et simple. Contrairement à Python, Go utilise des accolades {}
pour définir les blocs de code et nécessite des points-virgules à la fin des instructions (bien qu’ils soient généralement insérés automatiquement).
// Ceci est un commentaire sur une seule ligne
fmt.Println("Hello, World!")
/*
Ceci est un commentaire multi-lignes
s'étendant sur plusieurs lignes
*/
Règles de syntaxe de base en Go :
- Blocs de code : Définis par des accolades
{}
- Commentaires : Les commentaires sur une seule ligne commencent par
//
, les commentaires multi-lignes par/* */
- Instructions : Se terminent par des points-virgules (insérés automatiquement)
- Déclaration de package : Chaque fichier commence par une déclaration de package
3. Variables et types de données
Go est statiquement typé, ce qui signifie que vous devez déclarer les types de variables. Cependant, Go prend en charge l’inférence de type avec l’opérateur :=
.
Méthodes de déclaration de variables :
// Déclaration de type explicite
var name string = "John"
var age int = 25
// Inférence de type
name := "John"
age := 25
// Déclaration multiple de variables
var x, y int = 10, 20
x, y := 10, 20
Principaux types de données de base de Go :
- Types entiers :
int
,int8
,int16
,int32
,int64
,uint
,uint8
,uint16
,uint32
,uint64
,uintptr
- Types flottants :
float32
,float64
- Chaîne de caractères :
string
- Booléen :
bool
- Types complexes :
complex64
,complex128
3.1 Types numériques
Go fournit divers types numériques pour différents cas d’utilisation :
// Types entiers
var age int = 25
var smallNumber int8 = 127
var largeNumber int64 = 9223372036854775807
// Types flottants
var temperature float32 = 36.5
var pi float64 = 3.14159265359
// Nombres complexes
var complexNum complex64 = 3 + 4i
3.2 Type chaîne de caractères
Les chaînes en Go sont des séquences d’octets et sont immuables :
// Déclaration de chaîne
var greeting string = "Hello, Go!"
name := "Alice"
// Opérations sur les chaînes
fmt.Println(len(greeting)) // Longueur de la chaîne
fmt.Println(greeting[0]) // Accéder au premier caractère (octet)
fmt.Println(greeting[0:5]) // Découpage de chaîne
fmt.Println(strings.ToUpper(name)) // Conversion en majuscules
3.3 Type booléen
Le type booléen a deux valeurs : true
et false
:
var isActive bool = true
var isComplete bool = false
// Opérations booléennes
result1 := true && false // false
result2 := true || false // true
result3 := !true // false
4. Constantes
Les constantes sont déclarées en utilisant le mot-clé const
et ne peuvent pas être modifiées :
const Pi = 3.14159
const MaxUsers = 1000
// Constantes multiples
const (
StatusOK = 200
StatusNotFound = 404
StatusError = 500
)
// Constantes typées
const Version string = "1.0.0"
5. Structures de données
Go fournit plusieurs structures de données intégrées pour stocker et manipuler des données.
5.1 Tableaux
Les tableaux sont des séquences de taille fixe d’éléments du même type :
// Déclaration de tableau
var numbers [5]int = [5]int{1, 2, 3, 4, 5}
names := [3]string{"Alice", "Bob", "Charlie"}
// Accès aux éléments
fmt.Println(numbers[0]) // 1
numbers[0] = 10 // Modifier l'élément
// Longueur du tableau
fmt.Println(len(numbers)) // 5
5.2 Tranches (Slices)
Les tranches sont des tableaux dynamiques qui peuvent grandir et rétrécir :
// Déclaration de tranche
numbers := []int{1, 2, 3, 4, 5}
var emptySlice []int
// Création de tranches à partir de tableaux
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // [2, 3, 4]
// Opérations sur les tranches
numbers = append(numbers, 6) // Ajouter un élément
numbers = append(numbers, 7, 8, 9) // Ajouter plusieurs éléments
// Capacité et longueur de la tranche
fmt.Println(len(numbers)) // Longueur : 9
fmt.Println(cap(numbers)) // Capacité : 10 (peut varier)
5.3 Maps (Tableaux associatifs)
Les maps sont des collections non ordonnées de paires clé-valeur :
// Déclaration de map
student := map[string]interface{}{
"name": "John",
"age": 20,
"major": "Computer Science",
}
// Déclaration alternative
var scores map[string]int = make(map[string]int)
scores["math"] = 95
scores["science"] = 88
// Accès et modification
fmt.Println(student["name"])
student["age"] = 21
student["gpa"] = 3.8
// Accès sécurisé
if phone, exists := student["phone"]; exists {
fmt.Println(phone)
} else {
fmt.Println("Téléphone non fourni")
}
// Itération sur la map
for key, value := range student {
fmt.Printf("%s: %v\n", key, value)
}
5.4 Structures (Structs)
Les structures sont des collections de champs qui peuvent avoir différents types :
// Définition de structure
type Person struct {
Name string
Age int
City string
}
// Création d'instances de structure
person1 := Person{"Alice", 25, "New York"}
person2 := Person{
Name: "Bob",
Age: 30,
City: "London",
}
// Accès aux champs
fmt.Println(person1.Name)
person1.Age = 26
6. Opérations et opérateurs
Go fournit un riche ensemble d’opérateurs pour divers calculs et comparaisons.
- Opérateurs arithmétiques :
+
,-
,*
,/
,%
(modulo) - Opérateurs de comparaison :
==
,!=
,>
,<
,>=
,<=
- Opérateurs logiques :
&&
,||
,!
- Opérateurs bit à bit :
&
,|
,^
,<<
,>>
- Opérateurs d’affectation :
=
,+=
,-=
,*=
,/=
6.1 Opérateurs arithmétiques
a, b := 10, 3
fmt.Printf("Addition : %d\n", a + b) // 13
fmt.Printf("Soustraction : %d\n", a - b) // 7
fmt.Printf("Multiplication : %d\n", a * b) // 30
fmt.Printf("Division : %d\n", a / b) // 3
fmt.Printf("Modulo : %d\n", a % b) // 1
6.2 Opérateurs de comparaison
x, y := 5, 10
fmt.Printf("Égal : %t\n", x == y) // false
fmt.Printf("Non égal : %t\n", x != y) // true
fmt.Printf("Supérieur à : %t\n", x > y) // false
fmt.Printf("Inférieur à : %t\n", x < y) // true
6.3 Opérateurs logiques
a, b := true, false
fmt.Printf("Opération ET : %t\n", a && b) // false
fmt.Printf("Opération OU : %t\n", a || b) // true
fmt.Printf("Opération NON : %t\n", !a) // false
7. Contrôle de flux
Go fournit plusieurs instructions de contrôle de flux pour gérer l’exécution du programme.
7.1 Instructions if
age := 20
if age >= 18 {
fmt.Println("Adulte")
} else if age >= 13 {
fmt.Println("Adolescent")
} else {
fmt.Println("Enfant")
}
// if avec instruction courte
if score := 85; score >= 90 {
fmt.Println("Note : A")
} else if score >= 80 {
fmt.Println("Note : B")
} else {
fmt.Println("Note : C")
}
7.2 Boucles for
Go n’a qu’une seule construction de boucle : for
// Boucle for basique
for i := 0; i < 5; i++ {
fmt.Println(i)
}
// Boucle de style while
count := 0
for count < 5 {
fmt.Println(count)
count++
}
// Boucle infinie
for {
fmt.Println("Ceci s'exécutera indéfiniment")
break // Utiliser break pour sortir
}
// Boucle range (pour les tranches, tableaux, maps)
fruits := []string{"pomme", "banane", "cerise"}
for index, fruit := range fruits {
fmt.Printf("%d: %s\n", index, fruit)
}
7.3 Instructions switch
day := "Lundi"
switch day {
case "Lundi":
fmt.Println("Début de la semaine")
case "Vendredi":
fmt.Println("Le week-end approche")
case "Samedi", "Dimanche":
fmt.Println("Week-end !")
default:
fmt.Println("Jour ordinaire")
}
// Switch sans expression
score := 85
switch {
case score >= 90:
fmt.Println("Note : A")
case score >= 80:
fmt.Println("Note : B")
case score >= 70:
fmt.Println("Note : C")
default:
fmt.Println("Note : F")
}
8. Fonctions
Les fonctions en Go sont des citoyens de première classe et prennent en charge plusieurs valeurs de retour.
8.1 Fonctions de base
func greet(name string) string {
return "Bonjour, " + name + " !"
}
// Appel de la fonction
message := greet("John")
fmt.Println(message)
8.2 Valeurs de retour multiples
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("impossible de diviser par zéro")
}
return a / b, nil
}
// Utilisation de valeurs de retour multiples
result, err := divide(10, 2)
if err != nil {
fmt.Println("Erreur :", err)
} else {
fmt.Println("Résultat :", result)
}
8.3 Valeurs de retour nommées
func calculateRectangle(width, height float64) (area float64, perimeter float64) {
area = width * height
perimeter = 2 * (width + height)
return // retour nu
}
area, perimeter := calculateRectangle(5, 3)
fmt.Printf("Aire : %.2f, Périmètre : %.2f\n", area, perimeter)
8.4 Fonctions variadiques
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
fmt.Println(sum(1, 2, 3, 4)) // 10
fmt.Println(sum(5, 10, 15)) // 30
9. Pointeurs
Go a des pointeurs mais avec une syntaxe plus simple que C/C++ :
func modifyValue(x *int) {
*x = *x * 2
}
func main() {
value := 10
fmt.Println("Avant :", value) // 10
modifyValue(&value)
fmt.Println("Après :", value) // 20
}
10. Méthodes
Les méthodes sont des fonctions avec un argument récepteur :
type Rectangle struct {
Width float64
Height float64
}
// Méthode avec récepteur de valeur
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
// Méthode avec récepteur de pointeur
func (r *Rectangle) Scale(factor float64) {
r.Width *= factor
r.Height *= factor
}
rect := Rectangle{Width: 5, Height: 3}
fmt.Println("Aire :", rect.Area()) // 15
rect.Scale(2)
fmt.Println("Aire mise à l'échelle :", rect.Area()) // 60
11. Interfaces
Les interfaces définissent des signatures de méthode que les types peuvent implémenter :
type Shape interface {
Area() float64
Perimeter() float64
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14159 * c.Radius
}
func printShapeInfo(s Shape) {
fmt.Printf("Aire : %.2f, Périmètre : %.2f\n", s.Area(), s.Perimeter())
}
circle := Circle{Radius: 5}
printShapeInfo(circle)
12. Gestion des erreurs
Go utilise une gestion explicite des erreurs plutôt que des exceptions :
func readFile(filename string) (string, error) {
data, err := os.ReadFile(filename)
if err != nil {
return "", fmt.Errorf("échec de la lecture du fichier %s: %w", filename, err)
}
return string(data), nil
}
content, err := readFile("example.txt")
if err != nil {
fmt.Println("Erreur :", err)
return
}
fmt.Println("Contenu :", content)
13. Concurrence avec les goroutines
Les goroutines sont des threads légers gérés par l’environnement d’exécution Go :
func worker(id int) {
for i := 0; i < 3; i++ {
fmt.Printf("Travailleur %d: %d\n", id, i)
time.Sleep(time.Millisecond * 100)
}
}
func main() {
// Démarrer plusieurs goroutines
for i := 1; i <= 3; i++ {
go worker(i)
}
// Attendre que les goroutines se terminent
time.Sleep(time.Second)
fmt.Println("Tous les travailleurs ont terminé")
}
14. Canaux (Channels)
Les canaux sont utilisés pour la communication entre goroutines :
func producer(ch chan<- int) {
for i := 0; i < 5; i++ {
ch <- i // Envoyer une valeur au canal
time.Sleep(time.Millisecond * 100)
}
close(ch) // Fermer le canal une fois terminé
}
func consumer(ch <-chan int) {
for value := range ch {
fmt.Println("Reçu :", value)
}
}
func main() {
ch := make(chan int, 3) // Canal tamponné
go producer(ch)
consumer(ch)
fmt.Println("Communication par canal terminée")
}
15. Opérations sur les fichiers
Go fournit des méthodes simples pour lire et écrire des fichiers :
// Lecture de fichiers
data, err := os.ReadFile("example.txt")
if err != nil {
fmt.Println("Erreur de lecture du fichier :", err)
return
}
fmt.Println("Contenu du fichier :", string(data))
// Écriture de fichiers
content := "Bonjour, Go !\n"
err = os.WriteFile("output.txt", []byte(content), 0644)
if err != nil {
fmt.Println("Erreur d'écriture du fichier :", err)
return
}
fmt.Println("Fichier écrit avec succès")
16. Packages et modules
Les modules Go gèrent les dépendances et les versions des packages :
// Importation de packages de la bibliothèque standard
import (
"fmt"
"math"
"strings"
)
func main() {
fmt.Println(math.Sqrt(16)) // 4
fmt.Println(strings.ToUpper("go")) // GO
}
Pour créer votre propre package, créez un répertoire avec le nom de votre package et exportez les fonctions en capitalisant leurs noms.
17. Tests
Go a un support de test intégré :
// Dans le fichier math_test.go
package main
import "testing"
func TestAdd(t *testing.T) {
result := add(2, 3)
expected := 5
if result != expected {
t.Errorf("add(2, 3) = %d; attendu %d", result, expected)
}
}
func add(a, b int) int {
return a + b
}
Exécutez les tests avec : go test
18. Bonnes pratiques
- Utilisez
gofmt
pour formater votre code - Suivez les conventions de nommage de Go (camelCase pour les variables, PascalCase pour les exports)
- Gérez les erreurs explicitement
- Utilisez les interfaces pour l’abstraction
- Préférez la composition à l’héritage
- Écrivez des tests complets
- Utilisez la bibliothèque standard autant que possible
Ce tutoriel couvre les fonctionnalités essentielles de la programmation Go. Avec de la pratique, vous serez capable de créer des applications efficaces et concurrentes en utilisant les fonctionnalités puissantes de Go.